import aip
import httpx

from config.config import *
from .validate import *


class AIPOCR:
    def __init__(self):
        self.ocr = aip.AipOcr(BAIDU_APPID, BAIDU_APIKEY, BAIDU_SECRET)

    def basic(self, content=None, url=None):
        """
        通用文字识别
        """

        if not content:
            content = self.get_content(url)

        if not content:
            return None

        try:
            ocr_data = self.ocr.basicAccurate(content)
        except BaseException:
            ocr_data = {}

        data = []

        for x in ocr_data.get("words_result", []):
            value = str(x.get("words") or "").strip()

            if value:
                data.append(value)

        return data

    def idcard(self, content=None, url=None, front=True):
        """
        身份证识别
        """

        def fix_idcard_code(code):
            code = code.upper()
            code = code.replace("Ⅹ", "X")

            return code

        if not content:
            content = self.get_content(url)

        if not content:
            return None

        try:
            ocr_data = self.ocr.idcard(content, "front" if front else "back")
        except BaseException:
            ocr_data = {}

        if ocr_data.get("image_status") not in ("normal", "reversed_side"):
            return None

        if front:
            map = {
                "姓名": "姓名",
                "性别": "性别",
                "民族": "民族",
                "出生": "出生",
                "住址": "住址",
                "公民身份号码": "公民身份号码",
            }
        else:
            map = {"签发机关": "签发机关", "签发日期": "签发日期", "失效日期": "失效日期"}

        data = {}

        for k, v in ocr_data.get("words_result", {}).items():
            if k not in map:
                continue

            value = str(v.get("words", "")).strip()

            if value:
                data[map[k]] = value

        if data.get("公民身份号码"):
            data["公民身份号码"] = fix_idcard_code(data.get("公民身份号码"))

            if not validate_idcard(data.get("公民身份号码")):
                return None

        return data

    def bankcard(self, content=None, url=None):
        """
        银行卡识别
        """

        if not content:
            content = self.get_content(url)

        if not content:
            return None

        try:
            ocr_data = self.ocr.bankcard(content)
        except BaseException:
            ocr_data = {}

        map = {
            "bank_card_number": "卡号",
            "bank_name": "银行",
            "bank_card_type": "类型",
        }

        data = {}

        for k, v in ocr_data.get("result", {}).items():
            if k not in map:
                continue

            value = str(v or "").replace(" ", "").strip()

            if value:
                data[map[k]] = value
        if data.get("类型") == "1":
            data["类型"] = "借记卡"
        elif data.get("类型") == "2":
            data["类型"] = "信用卡"
        else:
            data = None

        return data

    def business_license(self, content=None, url=None, extend=False):
        """
        营业执照识别
        """

        def fix_business_license_code(code):
            code = code.upper()
            code = (
                code.replace("亅", "J")
                .replace("丅", "T")
                .replace("∪", "U")
                .replace("Ⅹ", "X")
            )

            division_code = code[2:8]
            division_code = division_code.replace("D", "0").replace("O", "0")

            return code[:2] + division_code + code[8:]

        if not content:
            content = self.get_content(url)

        if not content:
            return None

        try:
            ocr_data = self.ocr.businessLicense(content)
        except BaseException:
            ocr_data = {}

        map = {
            "社会信用代码": "统一社会信用代码",
            "单位名称": "单位名称",
            "类型": "类型",
            "地址": "地址",
            "法人": "法人",
            "成立日期": "成立日期",
        }

        data = {}

        for k, v in ocr_data.get("words_result", {}).items():
            if k not in map:
                continue

            value = v.get("words", "").strip()

            if value in ("无",):
                value = ""

            if value:
                data[map[k]] = value

        if len(data.get("统一社会信用代码", "")) != 18 or not data.get("地址"):
            if not extend:
                return None

            extend_data = self.lottery_sale_license(content)

            if not extend_data:
                return None

            data.update(
                {
                    "统一社会信用代码": extend_data.get("编号"),
                    "单位名称": extend_data.get("单位名称"),
                    "法人": extend_data.get("姓名"),
                    "地址": extend_data.get("地址"),
                }
            )
        else:
            if data.get("统一社会信用代码"):
                data["统一社会信用代码"] = fix_business_license_code(data.get("统一社会信用代码"))

                if not validate_business_license(data.get("统一社会信用代码")):
                    return None

        return data

    def lottery_sale_license(self, content=None, url=None):
        """
        彩票代销证识别
        """

        ocr_data = self.basic(content, url)

        if not ocr_data:
            return None

        data = {}

        found = False
        pre = None
        unit = None

        for x in ocr_data:
            x = x.replace("：", ":").strip()

            if "彩票代销证" in x:
                data["单位名称"] = x.replace("彩票代销证", "彩票代销点")

                found = True
            elif "中国福利彩票" in x:
                data["单位名称"] = "中国福利彩票代销点"

                found = True
            else:
                pass

            if x.startswith(":"):
                if data and pre:
                    data[list(data.keys())[-1]] += x[1:].strip()

                pre = None
            elif ":" in x:
                k, v = x.split(":", 1)

                for name in ("编号", "姓名", "地址"):
                    if name in k:
                        if name not in data:
                            pre = v.strip()
                            data[name] = pre

                if "发证单位" in k and "省" in v:
                    unit = v.split("省")[0].strip() + "省"
            else:
                pre = None

        if not found:
            return None

        for name in ("编号", "姓名", "地址"):
            if not data.get(name):
                return None

        data["单位名称"] += f'({data["编号"]})'

        if unit:
            data["单位名称"] = unit + data["单位名称"]

        if data.get("编号"):
            if not data.get("编号").isdecimal():
                return None

        return data

    def buidling_info(self, content=None, url=None):
        """
        二维码建筑信息识别
        """

        def fix_buidling_code(code):
            code = code.upper()
            code = code.replace("丅", "T")

            return code

        data = {}

        ocr_data = self.basic(content, url)

        if ocr_data:
            pre = None

            for x in ocr_data:
                x = x.replace("：", ":").strip()

                if ":" in x:
                    k, v = x.split(":", 1)

                    k = k.strip()
                    v = v.strip()

                    if v:
                        if k in ("楼栋编码", "房屋编码"):
                            data["编码"] = v
                            pre = None
                        elif k in ("标准地址", "房屋地址"):
                            data["地址"] = v
                            pre = "地址"
                        elif k in ("联系电话",):
                            data["电话"] = v
                            pre = None
                        else:
                            pre = None

                            if "编码" in k or "编号" in k:
                                if not data.get("编码"):
                                    data["编码"] = v
                                    pre = None
                            elif "地址" in k:
                                if not data.get("地址"):
                                    data["地址"] = v
                                    pre = "地址"
                            else:
                                if not data.get("编码"):
                                    if v.lower().replace("t", "").isdecimal():
                                        if len(v) in (19, 25):
                                            data["编码"] = v
                    else:
                        pre = None
                else:
                    if x and pre:
                        data[pre] += x

                    pre = None

        if data.get("编码"):
            if len(data.get("编码")) not in (19, 25):
                del data["编码"]
            else:
                if not data.get("编码").lower().replace("t", "").isdecimal():
                    del data["编码"]

        if not data.get("编码") or not data.get("地址"):
            ocr_data = self.qrcode(content, url)

            if ocr_data:
                for x in ocr_data:
                    x = x.replace("：", ":")

                    if ":" in x:
                        k, v = x.split(":", 1)

                        k = k.strip()
                        v = v.strip()

                        if v and v != "null":
                            if k in ("楼栋编码", "房屋编码"):
                                data["编码"] = v
                            elif k in ("标准地址", "房屋地址"):
                                data["地址"] = v
                            elif k in ("联系电话",):
                                data["电话"] = v
                            else:
                                pass

                if not data.get("编码"):
                    for x in ocr_data:
                        m = re.search(r"([0-9T]+)", x)

                        if m:
                            code = m.group(1)

                            if len(code) in (19, 25):
                                data["编码"] = code

                                break

        if data.get("编码"):
            data["编码"] = fix_buidling_code(data.get("编码"))

            if not validate_buidling_code(data.get("编码")):
                return None

        return data

    def qrcode(self, content=None, url=None):
        """
        二维码/条形码识别
        """

        if not content:
            content = self.get_content(url)

        if not content:
            return None

        try:
            ocr_data = self.ocr.qrcode(content)
        except BaseException:
            ocr_data = {}

        data = []

        if ocr_data.get("codes_result"):
            for code_result in ocr_data.get("codes_result"):
                for x in code_result.get("text", []):
                    x = str(x or "").strip()

                    if x:
                        data.append(x)

        return data

    def get_content(self, url):
        try:
            r = httpx.get(url)

            return r.content
        except BaseException:
            return None
